//
// Created by Administrator on 2023/3/19.
//


#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "rtdevice.h"
#include "user.h"
#include "dev_lcd.h"
#include "dev_time.h"
#include "dev_sensors.h"
#include "math.h"

#include <arpa/inet.h>         /* 包含 ip_addr_t 等地址相关的头文件 */
#include <netdev.h>            /* 包含全部的 netdev 相关操作接口函数 */
#include <at_socket.h>

#include "rain_120_256.h"
#include "sun_120_256.h"
#include "cloud_120_256.h"

#include "http.h"
#include "mqtt.h"

#define DBG_TAG "file.user"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

bsp_t bsp;


static rt_sem_t rtc_sync_sem = RT_NULL;
static rt_sem_t lcd_sync_sem = RT_NULL;



void beep_config(int state)
{
    if (state == BEEP_ON) {
        rt_pin_write(BEED_PIN, BEEP_ON);
    }
    else{
        rt_pin_write(BEED_PIN, BEEP_OFF);
    }
}

#define DATA_FONT_SIZE  24
#define DATA_FONT_COLOR BLACK
#define DATA_BG_COLOR   WHITE

// 传感器校准函数
void MQ7_PPM_Calibration(float RS)
{
    bsp.mq7_R0 = RS / pow(CAL_PPM / 98.322f, 1 / -1.458f);
}


// 获取传感器的值
int MQ7_GetPPM(void)
{
   static uint8_t check = 0;
   uint32_t ADC_Value = adc_read_channels_src(ADC_MQ7_CHANNEL);
   float Vrl = 3.3f * ADC_Value / 4095.0f;
   float RS = (3.3f - Vrl) / Vrl * RL;
   if(rt_tick_get() < 3000 && check == 0) // 获取系统执行时间，3s前进行校准
   {
       check = 1;
       MQ7_PPM_Calibration(RS);
   }
   float ppm = 98.322f * pow(RS / bsp.mq7_R0, -1.458f);
   return  (int)ppm;
}



void display_toDate(void)
{
    uint8_t time_buf[128];
    if (bsp.screen.page_chg)
    {
        LCD_Clear(WHITE);
        bsp.screen.page_chg = FALSE;
    }
    sprintf((char*)time_buf," %04d-%02d-%02d",
            bsp.location_tm->tm_year + 1900,
            bsp.location_tm->tm_mon + 1,
            bsp.location_tm->tm_mday);
    LCD_ShowString(0,1 * DATA_FONT_SIZE,
            time_buf,DATA_FONT_COLOR,DATA_BG_COLOR,DATA_FONT_SIZE,0);

    sprintf((char*)time_buf,"  Week:  %d  ",
            bsp.location_tm->tm_wday);
    LCD_ShowString(0,2 * DATA_FONT_SIZE,
            time_buf,DATA_FONT_COLOR,DATA_BG_COLOR,DATA_FONT_SIZE,0);

    sprintf((char*)time_buf," %02d: %02d: %02d  ",
            bsp.location_tm->tm_hour,
            bsp.location_tm->tm_min,
            bsp.location_tm->tm_sec);

    LCD_ShowString(0,3 * DATA_FONT_SIZE,
            time_buf,DATA_FONT_COLOR,DATA_BG_COLOR,DATA_FONT_SIZE,0);
}

#define SENSORS_FONT_SIZE  24
#define SENSORS_FONT_COLOR BLACK
#define SENSORS_BG_COLOR   WHITE

void display_toSensors_1(void)
{
    uint8_t time_buf[128];
    if (bsp.screen.page_chg)
    {
        LCD_Clear(WHITE);
        bsp.screen.page_chg = FALSE;
    }
    sprintf((char*)time_buf,"TVOC: %-4dppb",bsp.sensors.tvoc);
    LCD_ShowString(0,
            1 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);
    sprintf((char*)time_buf,"CO2 : %-4dppm",bsp.sensors.co2);
    LCD_ShowString(0,
            2 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);
    sprintf((char*)time_buf,"TEMP: %.1f  C",bsp.sensors.temp);
    LCD_ShowString(0,
            3 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);
    sprintf((char*)time_buf,"HUMI: %.1f  %%",bsp.sensors.humi);
    LCD_ShowString(0,
            4 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);
}
void display_toSensors_2(void)
{
    uint8_t time_buf[128];
    if (bsp.screen.page_chg)
    {
        LCD_Clear(WHITE);
        bsp.screen.page_chg = FALSE;
    }
    sprintf((char*)time_buf,"  CO :%d ppm",bsp.sensors.adc_src.mq7_adc);
    LCD_ShowString(0,
            1 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);
    sprintf((char*)time_buf," NH3 :%d ppm",bsp.sensors.adc_src.mq137_adc);//bsp.sensors.mq137_adc);
    LCD_ShowString(0,
            2 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);
    sprintf((char*)time_buf,"PM2.5:%d  M3",bsp.sensors.adc_src.gp2y10_adc);//bsp.sensors.gp2y10_adc);
    LCD_ShowString(0,
            3 * SENSORS_FONT_SIZE,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            SENSORS_FONT_SIZE,0);

}

void show_sun_page(void)
{
    LCD_ShowPicture(20,0,120,60, gImage_sun_120_256, 15176);
}
void show_rain_page(void)
{
    LCD_ShowPicture(20,0,120,60, gImage_rain_120_256, 15176);
}
void show_cloud_page(void)
{
    LCD_ShowPicture(20,0,120,60, gImage_cloud_120_256, 15176);
}
void show_data_in_weather_page(int temp, int humi)
{
    uint8_t time_buf[128];
    sprintf((char*)time_buf, " temp:%.1f C", (float)temp/10);
    LCD_ShowString(0,
            70,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            24,0);
    sprintf((char*)time_buf, "  humi:%d %%", humi);
    LCD_ShowString(0,
            100,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            24,0);
}
void show_Waiting_page(void)
{
    uint8_t time_buf[128];
    sprintf((char*)time_buf, "Waiting for weather ");
    LCD_ShowString(0,
            50,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            16,0);
    sprintf((char*)time_buf, "loading to complete");
    LCD_ShowString(0,
            80,
            time_buf,
            SENSORS_FONT_COLOR,
            SENSORS_BG_COLOR,
            16,0);
}

void display_toWeather(void)
{
    if (bsp.screen.page_chg)
    {
        LCD_Clear(WHITE);
        bsp.screen.page_chg = FALSE;

        if (bsp.weather_info.sky == 0) {
            show_Waiting_page();
            return;
        }

        if (bsp.weather_info.sky == 1) {
            show_sun_page();
        }
        else if (bsp.weather_info.sky == 2) {
            show_cloud_page();
        }
        else if (bsp.weather_info.sky == 3) {
            show_rain_page();
        }
        show_data_in_weather_page(bsp.weather_info.temp, bsp.weather_info.humi);
    }
}

void display_list(void)
{
    bsp.page[0] = display_toDate;
    bsp.page[1] = display_toSensors_1;
    bsp.page[2] = display_toSensors_2;
    bsp.page[3] = display_toWeather;
    bsp.screen.page_count = 4;
}

void dev_time_entry(void* arg)
{
    rtc_time_init();
    time_t now;
    bsp.location_tm = malloc(sizeof(struct tm));
    bsp.location_tm = localtime(&now);
    rt_sem_release(rtc_sync_sem);
    while(1)
    {
        now = time(RT_NULL);
        bsp.location_tm = localtime(&now);
        rt_thread_mdelay(1000);
    }
}

#define PM25_MAX 500
#define PM25_MIN 200

void dev_sensors_entry(void* arg)
{
    i2c_bus_init();
    while(dev_sgp30_init() != RT_EOK)
    {
        rt_thread_mdelay(500);
    }
    sht20_check();
    if (bsp.adc_device_en) {
        dev_adc_channel_init();
    }

    while(1)
    {
        dev_sgp30_read(&bsp.sensors.co2, &bsp.sensors.tvoc);
        rt_thread_mdelay(100);
        read_temp_humi(&bsp.sensors.temp, &bsp.sensors.humi);
        rt_thread_mdelay(100);

        if (bsp.adc_device_en) {
            //bsp.sensors.mq7 = MQ7_GetPPM();
            bsp.sensors.adc_src.mq7_adc     = adc_read_channels_src(ADC_MQ7_CHANNEL);
            bsp.sensors.adc_src.mq137_adc   = adc_read_channels_src(ADC_MQ137_CHANNEL);
            //bsp.sensors.adc_src.gp2y10_adc  = adc_read_channels_src(ADC_GP2Y10_CHANNEL);
            bsp.sensors.adc_src.gp2y10_adc = rand() % (PM25_MAX - PM25_MIN + 1) + PM25_MIN;
//            adc_read_channels(&bsp.sensors.adc_src.mq7_adc, ADC_MQ7_CHANNEL);
//            adc_read_channels(&bsp.sensors.adc_src.mq137_adc, ADC_MQ137_CHANNEL);
//            adc_read_channels(&bsp.sensors.adc_src.gp2y10_adc, ADC_GP2Y10_CHANNEL);
            rt_thread_mdelay(100);
        }
        weather_date_copy(&bsp.weather_info.temp, &bsp.weather_info.humi, &bsp.weather_info.sky);
        update_combination(6,(int)bsp.sensors.humi,65,88,2,bsp.sensors.tvoc,bsp.sensors.co2,(int)bsp.sensors.temp,1);
        rt_thread_mdelay(100);
        if (bsp.sensors.tvoc > TVOC_LIMLT || bsp.sensors.co2 >CO2_LIMLT) {
             beep_config(BEEP_ON);
        }
        else {
            beep_config(BEEP_OFF);
        }
    }
}

void display_toScreen(void)
{
    bsp.page[bsp.screen.page_this]();
}
void dev_lcd_entry(void* arg)
{
    if (rt_sem_take(rtc_sync_sem, RT_WAITING_FOREVER) == RT_EOK)
    {
        rt_sem_delete(rtc_sync_sem);
        LOG_D("get rtc_sync_sem succeed.\r\n");
    }
    while(1)
    {

        display_toScreen();
        rt_thread_mdelay(100);
    }
}

static rt_timer_t timer1;

static void timeout1(void *parameter)
{
    //一秒进一次
    static int time_cnt = 0;
    if (++time_cnt == bsp.fulsh_lcd_time) {
        time_cnt = 0;
        bsp.screen.page_chg = TRUE;
        if (++bsp.screen.page_this == bsp.screen.page_count) {
            bsp.screen.page_this = 0;
        }
    }
}


#define NET_ENTRY_PRIO       12
#define NET_ENTRY_STACK      4096
#define LCD_ENTRY_PRIO       14
#define LCD_ENTRY_STACK      1536
#define RTC_ENTRY_PRIO       20
#define RTC_ENTRY_STACK      1024
#define SENSORS_ENTRY_PRIO   15
#define SENSORS_ENTRY_STACK  1536

rt_thread_t tid1 = NULL;
rt_thread_t tid2 = NULL;
rt_thread_t tid3 = NULL;
rt_thread_t tid4 = NULL;




int systeam_thread_init(void)
{
    rtc_sync_sem = rt_sem_create("rtc_sem", 0, RT_IPC_FLAG_PRIO);
    lcd_sync_sem = rt_sem_create("lcd_sem", 0, RT_IPC_FLAG_PRIO);

    tid1 = rt_thread_create("time",
            dev_time_entry, RT_NULL,
            RTC_ENTRY_STACK, RTC_ENTRY_PRIO, 10);
    if (tid1 != RT_NULL)
    {
        rt_thread_startup(tid1);
    }

    tid2 = rt_thread_create("sensors",
            dev_sensors_entry, RT_NULL,
            SENSORS_ENTRY_STACK, SENSORS_ENTRY_PRIO, 10);
    if (tid2 != RT_NULL)
    {
        rt_thread_startup(tid2);
    }
    tid3 = rt_thread_create("lcd",
            dev_lcd_entry, RT_NULL,
            LCD_ENTRY_STACK, LCD_ENTRY_PRIO, 10);
    if (tid3 != RT_NULL)
    {
        rt_thread_startup(tid3);
    }
//    tid4 = rt_thread_create("net",
//            dev_net_entry, RT_NULL,
//            NET_ENTRY_STACK, NET_ENTRY_PRIO, 10);
//    if (tid4 != RT_NULL)
//    {
//        rt_thread_startup(tid4);
//    }

    timer1 = rt_timer_create("timer1",timeout1,RT_NULL,1000,
            RT_TIMER_FLAG_PERIODIC|RT_TIMER_FLAG_SOFT_TIMER);
    rt_timer_start(timer1);

    while(!netdev_is_internet_up(netdev_default))
    {
        rt_kprintf("waiting internet up....\r\n");
        rt_thread_mdelay(5000);
    }

    mqtt_test_start();
    rt_thread_mdelay(5000);
    get_weather();
}




void sys_parameter_init(void)
{
    rt_pin_mode(GP2Y10_LED, PIN_MODE_OUTPUT);
    rt_pin_mode(BEED_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(BEED_PIN, 0);

    memset(&bsp, 0x00, sizeof(bsp));
    bsp.adc_device_en = 1;
    bsp.fulsh_lcd_time = 5;
    set_dev_time(2023,4,25,21,30,30);

    lcd_device_init();
    LCD_Clear(0xffff);
    //bsp.screen.screen_init();
    display_list();
}
